﻿/**
 * Copyright (C) 2012 original author and authors
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Collections;
using NGuice.Inject.Internal.Util;
using NGuice.Inject.Spi;
using System.Threading;
using System.Reflection;
using NGuice.Inject.Util;

namespace NGuice.Inject.Internal
{
    //complete!
    /// <summary>
    /// 默认注入器的实现
    /// </summary>
    public sealed class InjectorImpl : Injector, ILookups
    {
        /// <summary>
        /// 控制注入器行为的选项
        /// </summary>
        public class InjectorOptions
        {
            internal readonly Stage stage;

            internal readonly bool jitDisabled;

            internal readonly bool disableCircularProxies;

            internal InjectorOptions(Stage stage, bool jitDisabled, bool disableCircularProxies)
            {
                this.stage = stage;
                this.jitDisabled = jitDisabled;
                this.disableCircularProxies = disableCircularProxies;
            }

            public string ToString()
            {
                return new ToStringBuilder(this.GetType())
                                    .Add("stage", stage)
                                    .Add("jitDisabled", jitDisabled)
                                    .Add("disableCircularProxies", disableCircularProxies)
                                    .ToString();
            }
        }

        /** 在JIT即时编译期间的一些限制枚举 */
        public enum JitLimitation
        {
            /** 不允许JIT绑定 */
            NO_JIT,
            /** 允许存在的即时编译绑定，但不允许新创建的即时编译绑定 */
            EXISTING_JIT,
            /** 都允许 */
            NEW_OR_EXISTING_JIT,
        }

        internal readonly IState state;

        internal readonly InjectorImpl parent;
        internal readonly BindingsMultimap bindingsMultimap = new BindingsMultimap();

        internal readonly InjectorOptions options;

        /** Just-in-time binding cache. Guarded by state.lock() */
        //readonly Map<Key<?>, BindingImpl<?>> jitBindings = Maps.newHashMap();
        internal readonly IDictionary<Key, IBindingImpl> jitBindings = new Dictionary<Key, IBindingImpl>();

        internal ILookups lookups = null;

        internal InjectorImpl(InjectorImpl parent, IState state, InjectorOptions injectorOptions)
        {
            this.parent = parent;
            this.state = state;
            this.options = injectorOptions;
            lookups = new DeferredLookups(this);
            this.constructors = new ConstructorInjectorStore(this);
            if (parent != null)
            {
                localContext = parent.localContext;
            }
            else
            {
                localContext = new ThreadLocal<object[]>(() =>
                {
                    return new object[1];
                });
            }
        }

        internal void Index()
        {
            foreach (IBinding binding in state.GetExplicitBindingsThisLevel().Values)
            {
                Index(binding);
            }
        }

        internal void Index(IBinding binding)
        {
            bindingsMultimap.Put(binding.Key.TypeLiteral, binding);
        }

        public IList<IBinding<T>> FindBindingsByType<T>()
        {
            return bindingsMultimap.GetAll<T>();
        }

        public BindingImpl<T> GetBinding<T>(Key<T> key)
        {
            Errors errors = new Errors(key);
            try
            {
                BindingImpl<T> result = GetBindingOrThrow(key, errors, JitLimitation.EXISTING_JIT);
                errors.ThrowConfigurationExceptionIfErrorsExist();
                return result;
            }
            catch (ErrorsException e)
            {
                throw new ConfigurationException(errors.Merge(e.Errors).Messages);
            }
        }

        IBinding Injector.GetBinding(Key key)
        {
            return GetBinding(key);
        }

        /// <summary>
        /// 非泛型方法
        /// </summary>
        /// <param name="key">必须具有泛型参数的KEY</param>
        /// <returns></returns>
        public IBindingImpl GetBinding(Key key)
        {
            MethodInfo[] methods = GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance);
            foreach (MethodInfo method in methods)
            {
                if (method.Name == "GetBinding")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (IBindingImpl)method.MakeGenericMethod(key.GetType().GetGenericArguments()[0])
                              .Invoke(this, new object[] { key });
                    }
                    else if (method.IsGenericMethod)
                    {
                        //不是泛型定义方法，可以直接调用
                        return (IBindingImpl)method.Invoke(this, new object[] { key });
                    }
                }
            }
            throw new NotSupportedException("the generic method GetProvidedKey do not exist!");
            //通过反射调用泛型方法
            //return (IBindingImpl)this.GetType().GetMethod("GetBinding").MakeGenericMethod(key.GetType().GetGenericArguments()).Invoke(this, new object[] { key });
        }

        public IBinding<T> GetExistingBinding<T>(Key<T> key)
        {
            // 检查显式的绑定,例如被模块创建的绑定
            BindingImpl<T> explicitBinding = state.GetExplicitBinding(key);
            if (explicitBinding != null)
            {
                return explicitBinding;
            }
            lock (state)
            {
                //查看是否有jit绑定已经为此key创建
                for (InjectorImpl injector = this; injector != null; injector = injector.parent)
                {
                    BindingImpl<T> jitBinding = (BindingImpl<T>)injector.jitBindings[key];
                    if (jitBinding != null)
                    {
                        return jitBinding;
                    }
                }
            }

            //如果key为提供者，我们必须检查他提供的类型是否存在，如果存在，我们必须为提供者创建binding
            if (IsProvider(key))
            {
                try
                {
                    //T为IProvider<?>类型,返回的Key中泛型参数为?,
                    dynamic providedKey = GetProvidedKey(key, new Errors());
                    //TODO:递归调用！由于C#不支持通配符泛型，如果递归调用，将只能使用反射方法。
                    //但这似乎影响性能，因此暂时先采用动态参数调用的方式进行，在将来版本中再寻求更好的解决方法
                    if (GetExistingBinding(providedKey) != null)
                    {
                        return GetBinding(key);
                    }
                }
                catch (ErrorsException e)
                {
                    throw new ConfigurationException(e.Errors.Messages);
                }
            }

            // No existing binding exists.
            return null;
        }

        /// <summary>
        /// 获取一个绑定实现。首先先检查parent是否具有绑定。如果parent具有绑定，且绑定是范围化的，他将使用
        /// parent的绑定。否则，他检查显式的绑定。如果没有找到显式的绑定，他将查找即时的绑定
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="errors"></param>
        /// <param name="jitType"></param>
        /// <returns></returns>
        BindingImpl<T> GetBindingOrThrow<T>(Key<T> key, Errors errors, JitLimitation jitType)
        {
            // Check explicit bindings, i.e. bindings created by modules.
            BindingImpl<T> binding = state.GetExplicitBinding(key);
            if (binding != null)
            {
                return binding;
            }

            // Look for an on-demand binding.
            return GetJustInTimeBinding(key, errors, jitType);
        }

        /// <summary>
        /// 非泛型方法
        /// </summary>
        /// <param name="key"></param>
        /// <param name="errors"></param>
        /// <param name="jitType"></param>
        /// <returns></returns>
        IBindingImpl GetBindingOrThrowForNoGeneric(Key key, Errors errors, JitLimitation jitType)
        {
            MethodInfo[] methods = GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (MethodInfo method in methods)
            {
                if (method.Name == "GetBindingOrThrow")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (IBindingImpl)method.MakeGenericMethod(key.GetType().GetGenericArguments()[0])
                              .Invoke(this, new object[] { key, errors, jitType });
                    }
                }
            }
            throw new IllegalStateException("no GetBindingOrThrow method is found");
        }

        public IBinding<T> GetBinding<T>()
        {
            return GetBinding(Key<T>.Get());
        }

        public Injector Parent
        {
            get
            {
                return parent;
            }
        }

        public Injector CreateChildInjector<T>(IEnumerable<T> modules)
            where T : IModule
        {
            return new InternalInjectorCreator().ParentInjector(this)
                                                .AddModules(modules.Cast<IModule>())
                                                .Build();
        }

        public Injector CreateChildInjector(params IModule[] modules)
        {
            return CreateChildInjector<IModule>(ImmutableList<IModule>.Of(modules));
        }

        /// <summary>
        /// 返回一个指定key的即时的绑定，如果必要则创建
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="errors"></param>
        /// <param name="jitType"></param>
        /// <returns></returns>
        /// <exception cref="ErrorsException">如果不能创建绑定</exception>
        private BindingImpl<T> GetJustInTimeBinding<T>(Key<T> key, Errors errors, JitLimitation jitType)
        {

            bool jitOverride = IsProvider(key) || IsMembersInjector(key);
            if (options.jitDisabled && jitType == JitLimitation.NO_JIT && !jitOverride)
            {
                throw errors.JITDisabled(key).ToException();
            }

            lock (state)
            {
                // first try to find a JIT binding that we've already created
                for (InjectorImpl injector = this; injector != null; injector = injector.parent)
                {
                    // we only store bindings that match their key
                    BindingImpl<T> binding = injector.jitBindings.ContainsKey(key) ? (BindingImpl<T>)injector.jitBindings[key] : null;

                    if (binding != null)
                    {
                        return binding;
                    }
                }

                if (options.jitDisabled && jitType != JitLimitation.NEW_OR_EXISTING_JIT && !jitOverride)
                {
                    throw errors.JITDisabled(key).ToException();
                }
                else
                {
                    return CreateJustInTimeBindingRecursive(key, errors);
                }
            }
        }

        /** Returns true if the key type is Provider (but not a subclass of Provider). */
        private static bool IsProvider(Key key)
        {
            Type keyGenericType = key.GetType().GetGenericArguments()[0];
            if (keyGenericType.IsGenericType && keyGenericType.GetGenericTypeDefinition().Equals(typeof(IProvider<>).GetGenericTypeDefinition()))
                return true;
            //while (!keyGenericType.IsGenericType && keyGenericType.BaseType != typeof(object))
            //{
            //    //找到超类的泛型类型
            //    keyGenericType = keyGenericType.BaseType;
            //}
            //if (keyGenericType == typeof(object))
            //    return false;
            //else if (typeof(IProvider).IsAssignableFrom(keyGenericType))
            //    return true;
            return false;
        }

        private static Key<T> GetProvidedKey<T>(Key<IProvider<T>> key, Errors errors)
        {
            return key.OfType<T>();
        }

        /// <summary>
        /// 非泛型方法
        /// </summary>
        /// <param name="key">Key中必须具有泛型参数，且泛型参数类型必须为IProvider&lt&gt的子类</param>
        /// <param name="errors"></param>
        /// <returns>返回Key中泛型参数IProvider中泛型参数类型的key</returns>
        private static Key GetProvidedKey(Key key, Errors errors)
        {
            Type providerGenericType = GetKeyGenericArgGenericType(key, "IProvider`1");
            return Key<object>.GetForType(providerGenericType);
            //throw new NotSupportedException("the generic method GetProvidedKey do not exist!");
        }

        private static Type GetKeyGenericArgGenericType(Key key, string interfaceName)
        {
            return key.GetType().GetGenericArguments()[0].GetInterface(interfaceName).GetGenericArguments()[0];
        }

        /** Returns true if the key type is MembersInjector (but not a subclass of MembersInjector). */
        private static bool IsMembersInjector(Key key)
        {
            Type keyGenericType = key.TypeLiteral;
            if (keyGenericType.IsGenericType && keyGenericType.GetGenericTypeDefinition().Equals(typeof(IMembersInjector<>).GetGenericTypeDefinition()))
                return true;
            return false;
        }

        /// <summary>
        /// 此方法大量使用反射，由于C#泛型的特性，只能使用反射+dynamic的方式调用类型化的泛型对象
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">key中泛型参数必须为IMembersInjector&ltT&gt及其子类</param>
        /// <param name="errors"></param>
        /// <returns></returns>
        private IBindingImpl CreateMembersInjectorBinding<T>(Key key, Errors errors)
        {
            Type membersInjectorType = key.TypeLiteral.GetGenericArguments()[0];
            dynamic membersInjector = membersInjectorStore.Get<T>(membersInjectorType, errors);

            //InternalFactory<IMembersInjector<T>> factory = new ConstantFactory<IMembersInjector<T>>(
            //    Initializables.Of(membersInjector));
            object o = Initializables.Of(membersInjector);
            InternalFactory factory = (InternalFactory)typeof(ConstantFactory<>).MakeGenericType(membersInjectorType)
                                                               .GetConstructor(new Type[] { o.GetType()})
                                                               .Invoke(new object[] {o});
            //return new InstanceBindingImpl<IMembersInjector<T>>(this, key, SourceProvider.UNKNOWN_SOURCE,
            //    factory, ImmutableSet<InjectionPoint>.Of(), membersInjector);
            return (IBindingImpl)typeof(InstanceBindingImpl<>).MakeGenericType(membersInjectorType)
                                                .GetConstructor(new Type[] { this.GetType(), key.GetType(), typeof(object), factory.GetType(),
                                                                             typeof(ImmutableSet<InjectionPoint>), membersInjector.GetType()})
                                                .Invoke(new object[] { this, key, SourceProvider.UNKNOWN_SOURCE, factory, ImmutableSet<InjectionPoint>.Of(), 
                                                                       membersInjector });
        }

        /// <summary>
        /// 非泛型方法！
        /// </summary>
        /// <param name="key">其泛型参数必须为IMembersInjector类型的子类</param>
        /// <param name="errors"></param>
        /// <returns></returns>
        private IBindingImpl CreateMembersInjectorBinding(Key key, Errors errors)
        {
            MethodInfo[] methods = this.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (MethodInfo method in methods)
            {
                if (method.Name == "CreateMembersInjectorBinding")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (IBindingImpl)method.MakeGenericMethod(GetKeyGenericArgGenericType(key, "IMembersInjector`1"))
                              .Invoke(this, new object[] { key, errors });
                    }
                    else if (method.IsGenericMethod)
                    {
                        //不是泛型定义，可以直接调用
                        return (IBindingImpl)method.Invoke(this, new object[] { key, errors });
                    }
                }
            }
            throw new NotSupportedException("the generic method CreateMembersInjectorBinding do not exist!");
        }

        /// <summary>
        /// 创建一个合成的到Provider的binding
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key">泛型参数必须为IProvider的子类</param>
        /// <param name="errors"></param>
        /// <returns></returns>
        private IBindingImpl CreateProviderBinding<T>(Key key, Errors errors)
        {
            Key<T> providedKey = (Key<T>)GetProvidedKey(key, errors);
            BindingImpl<T> delegatee = GetBindingOrThrow(providedKey, errors, JitLimitation.NO_JIT);
            return new ProviderBindingImpl<T>(this, key, delegatee);
        }

        /// <summary>
        /// 非泛型方法！
        /// </summary>
        /// <param name="key">泛型参数必须为IProvider的泛型子类</param>
        /// <param name="errors"></param>
        /// <returns></returns>
        private IBindingImpl CreateProviderBinding(Key key, Errors errors)
        {
            MethodInfo[] methods = this.GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance);
            foreach (MethodInfo method in methods)
            {
                if (method.Name == "CreateProviderBinding")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (IBindingImpl)method.MakeGenericMethod(GetKeyGenericArgGenericType(key, "IProvider`1"))
                              .Invoke(this, new object[] { key, errors });
                    }
                    else if (method.IsGenericMethod)
                    {//不是方法定义，直接可以调用
                        return (IBindingImpl)method.Invoke(this, new object[] { key, errors });
                    }
                }
            }
            throw new NotSupportedException("the generic method CreateProviderBinding do not exist!");
        }

        private class ProviderBindingImpl<T> : BindingImpl<IProvider<T>>, IProviderBinding<IProvider<T>>, IHasDependencies
        {
            internal readonly BindingImpl<T> providedBinding;

            internal ProviderBindingImpl(InjectorImpl injector, Key key, IBinding<T> providedBinding)
                : base(injector, key, providedBinding.Source,
                        CreateInternalFactory(providedBinding),
                        Scoping.UNSCOPED)
            {
                this.providedBinding = (BindingImpl<T>)providedBinding;
            }

            private class ProviderInternalFactory : InternalFactory<IProvider<T>>
            {
                IProvider<T> provider;

                public ProviderInternalFactory(IProvider<T> provider)
                {
                    this.provider = provider;
                }

                public IProvider<T> Get(Errors errors, InternalContext context, Dependency dependency, bool linked)
                {
                    return provider;
                }

                object InternalFactory.Get(Errors errors, InternalContext context, Dependency dependency, bool linked)
                {
                    return Get(errors, context, dependency, linked);
                }
            }

            static InternalFactory<IProvider<T>> CreateInternalFactory(IBinding<T> providedBinding)
            {
                IProvider<T> provider = providedBinding.Provider;
                return new ProviderInternalFactory(provider);
            }

            public Key<T> ProvidedKey
            {
                get
                {
                    return providedBinding.Key;
                }
            }

            public override V AcceptTargetVisitor<V>(IBindingTargetVisitor<IProvider<T>, V> visitor)
            {
                return visitor.Visit(this);
            }

            public override void ApplyTo(IBinder binder)
            {
                throw new NoSuchElementException("This element represents a synthetic binding.");
            }

            public override string ToString()
            {
                return new ToStringBuilder(typeof(IProviderBinding<>))
                    .Add("key", Key)
                    .Add("providedKey", ProvidedKey)
                    .ToString();
            }

            Key IProviderBinding.ProvidedKey
            {
                get { return ProvidedKey; }
            }

            public ISet<Dependency> Dependencies
            {
                get
                {
                    return ImmutableSet<Dependency>.Of(Dependency<T>.Get(ProvidedKey));
                }
            }

            public override bool Equals(object obj)
            {
                if (obj is ProviderBindingImpl<T>)
                {
                    ProviderBindingImpl<T> o = (ProviderBindingImpl<T>)obj;
                    return Key.Equals(o.Key)
                      && Scoping.Equals(Scoping)
                      && Objects.Equal(providedBinding, o.providedBinding);
                }
                else
                {
                    return false;
                }
            }

            public override int GetHashCode()
            {
                return Objects.GetHashCode(Key, Scoping, providedBinding);
            }

            public new Key Key
            {
                get { return base.Key; }
            }

            public new IProvider Provider
            {
                get { return base.Provider; }
            }
        }

        /// <summary>
        /// 转换一个常数字符串绑定到请求的类型
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="errors"></param>
        /// <returns>如果能被解析则返回binding，如果不存在则返回null</returns>
        /// <exception cref="ErrorsException">在解析binding期间发生错误</exception>
        private BindingImpl<T> ConvertConstantStringBinding<T>(Key<T> key, Errors errors)
        {
            // 查找常数字符串绑定
            Key<string> stringKey = key.OfType<string>();
            BindingImpl<string> stringBinding = state.GetExplicitBinding(stringKey);
            if (stringBinding == null || !stringBinding.IsConstant())
            {
                return null;
            }

            string stringValue = stringBinding.Provider.Get();
            object source = stringBinding.Source;

            // Find a matching type converter.
            Type type = key.TypeLiteral;
            TypeConverterBinding typeConverterBinding = state.GetConverter<T>(stringValue, errors, source);

            if (typeConverterBinding == null)
            {
                // No converter can handle the given type.
                return null;
            }

            // Try to convert the string. A failed conversion results in an error.
            try
            {
                // This cast is safe because we double check below.
                T converted = (T)typeConverterBinding.TypeConverter.Convert(stringValue, type);

                if (converted == null)
                {
                    throw errors.ConverterReturnedNull(stringValue, source, type, typeConverterBinding)
                        .ToException();
                }

                //if (!type.getRawType().isInstance(converted)) {
                //  throw errors.ConversionTypeError(stringValue, source, type, typeConverterBinding, converted)
                //      .ToException();
                //}

                return new ConvertedConstantBindingImpl<T>(this, key, converted, stringBinding, typeConverterBinding);
            }
            catch (ErrorsException e)
            {
                throw e;
            }
            catch (ApplicationException e)
            {
                throw errors.ConversionError(stringValue, source, type, typeConverterBinding, e)
                    .ToException();
            }
        }

        private class ConvertedConstantBindingImpl<T> : BindingImpl<T>, IConvertedConstantBinding<T>
        {
            readonly T value;
            readonly IProvider<T> provider;
            readonly IBinding<String> originalBinding;
            readonly TypeConverterBinding typeConverterBinding;

            internal ConvertedConstantBindingImpl(InjectorImpl injector, Key<T> key, T value,
                                                  IBinding<string> originalBinding,
                                                  TypeConverterBinding typeConverterBinding)
                : base(injector, key, originalBinding.Source,
                      new ConstantFactory<T>(Initializables.Of(value)), Scoping.UNSCOPED)
            {
                this.value = value;
                provider = Providers.Of(value);
                this.originalBinding = originalBinding;
                this.typeConverterBinding = typeConverterBinding;
            }

            public override IProvider<T> Provider
            {
                get
                {
                    return provider;
                }
            }

            public override V AcceptTargetVisitor<V>(IBindingTargetVisitor<T, V> visitor)
            {
                return visitor.Visit(this);
            }

            public T Value
            {
                get { return value; }
            }

            public TypeConverterBinding TypeConverterBinding
            {
                get { return typeConverterBinding; }
            }

            public Key<string> SourceKey
            {
                get { return originalBinding.Key; }
            }

            public ISet<Dependency> Dependencies
            {
                get { return ImmutableSet<Dependency>.Of(Dependency<string>.Get(SourceKey)); }
            }

            public override void ApplyTo(IBinder binder)
            {
                throw new NotSupportedException("This element represents a synthetic binding.");
            }

            public override string ToString()
            {
                return new ToStringBuilder(typeof(IConvertedConstantBinding<T>))
                    .Add("key", Key)
                    .Add("sourceKey", SourceKey)
                    .Add("value", value)
                    .ToString();
            }

            public override bool Equals(object obj)
            {
                if (obj is ConvertedConstantBindingImpl<T>)
                {
                    ConvertedConstantBindingImpl<T> o = (ConvertedConstantBindingImpl<T>)obj;
                    return Key.Equals(o.Key)
                      && Scoping.Equals(o.Scoping)
                      && Objects.Equal(value, o.value);
                }
                else
                {
                    return false;
                }
            }

            public override int GetHashCode()
            {
                return Objects.GetHashCode(Key, Scoping, value);
            }
        }

        internal void InitializeBinding<T>(BindingImpl<T> binding, Errors errors)
        {
            if (binding is ConstructorBindingImpl<T>)
            {
                ((ConstructorBindingImpl<T>)binding).Initialize(this, errors);
            }
        }

        internal void InitializeJitBinding<T>(BindingImpl<T> binding, Errors errors)
        {
            // 提前一点将大部分构造的binding放入字典中。这使得我们能够处理循环依赖。例如：FooImpl-》BarImpl-》FooImpl
            // 注意：我们不需要在注入器创建时在state.Lock中同步！
            if (binding is ConstructorBindingImpl<T>)
            {
                Key<T> key = binding.Key;
                jitBindings.Add(key, binding);
                bool successful = false;
                ConstructorBindingImpl<T> cb = (ConstructorBindingImpl<T>)binding;
                try
                {
                    cb.Initialize(this, errors);
                    successful = true;
                }
                finally
                {
                    if (!successful)
                    {
                        // We do not pass cb.getInternalConstructor as the second parameter
                        // so that cached exceptions while constructing it get stored.
                        // See TypeListenerTest#testTypeListenerThrows
                        RemoveFailedJitBinding(key, null);
                        Cleanup(binding, new HashSet<Key>());
                    }
                }
            }
        }

        /**
         * Iterates through the binding's dependencies to clean up any stray bindings that were leftover
         * from a failed JIT binding. This is required because the bindings are eagerly &
         * optimistically added to allow circular dependency support, so dependencies may pass where they
         * should have failed.
         */
        private bool Cleanup(IBindingImpl binding, ISet<Key> encountered)
        {
            bool bindingFailed = false;
            ISet<Dependency> deps = GetInternalDependencies(binding);
            foreach (Dependency dep in deps)
            {
                Key depKey = dep.Key;
                InjectionPoint ip = dep.InjectionPoint;
                if (encountered.Add(depKey))
                { // only check if we haven't looked at this key yet
                    IBindingImpl depBinding = jitBindings[depKey];
                    if (depBinding != null)
                    { // if the binding still exists, validate
                        bool failed = Cleanup(depBinding, encountered); // if children fail, we fail
                        if (depBinding is ConstructorBindingImpl)
                        {
                            dynamic dynBinding = depBinding;//TODO:泛型没有通配符，使用动态对象调用方法!
                            //ConstructorBindingImpl ctorBinding = (ConstructorBindingImpl)depBinding;
                            ip = dynBinding.GetInternalConstructor();
                            if (!dynBinding.IsInitialized())
                            {
                                failed = true;
                            }
                        }
                        if (failed)
                        {
                            RemoveFailedJitBinding(depKey, ip);
                            bindingFailed = true;
                        }
                    }
                    else if (state.GetExplicitBinding(depKey) == null)
                    {
                        // ignore keys if they were explicitly bound, but if neither JIT
                        // nor explicit, it's also invalid & should let parent know.
                        bindingFailed = true;
                    }
                }
            }
            return bindingFailed;
        }

        /// <summary>
        /// 当构造JIT绑定时，清除可能已经缓存的所有状态
        /// </summary>
        /// <param name="key"></param>
        /// <param name="ip"></param>
        private void RemoveFailedJitBinding(Key key, InjectionPoint ip)
        {
            jitBindings.Remove(key);
            membersInjectorStore.Remove(key.TypeLiteral);
            if (ip != null)
            {
                constructors.Remove(ip);
            }
        }

        private ISet<Dependency> GetInternalDependencies(IBindingImpl binding)
        {
            if (binding is ConstructorBindingImpl)
            {
                //C#中泛型没有通配符，使用动态对象解决此问题
                dynamic dynBinding = binding;
                return dynBinding.GetInternalDependencies();
            }
            else if (binding is IHasDependencies)
            {
                return ((IHasDependencies)binding).Dependencies;
            }
            else
            {
                return ImmutableSet<Dependency>.Of();
            }
        }

        /// <summary>
        /// 为具有给定scope的一个可注入类型创建一个绑定。如果没有指定，则在指定类型上查找一个scope
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="scoping"></param>
        /// <param name="source"></param>
        /// <param name="errors"></param>
        /// <param name="jitBinding"></param>
        /// <returns></returns>
        internal BindingImpl<T> CreateUninitializedBinding<T>(Key<T> key, Scoping scoping, object source,
           Errors errors, bool jitBinding)
        {
            Type rawType = key.TypeLiteral;

            // Don't try to inject arrays, or enums.
            if (rawType.IsArray || rawType.IsEnum)
            {
                throw errors.MissingImplementation(key).ToException();
            }

            //TODO:C#中无需TypeLiteral类型？？？？？？？？？？
            //// Handle TypeLiteral<T> by binding the inner type
            //if (rawType == TypeLiteral) {
            //  @SuppressWarnings("unchecked") // we have to fudge the inner type as Object
            //  BindingImpl<T> binding = (BindingImpl<T>) createTypeLiteralBinding(
            //      (Key<TypeLiteral<Object>>) key, errors);
            //  return binding;
            //}

            // Handle @ImplementedBy
            ImplementedByAttribute implementedBy = rawType.GetCustomAttributes(typeof(ImplementedByAttribute), false).Length != 0
                                                   ? (ImplementedByAttribute)rawType.GetCustomAttributes(typeof(ImplementedByAttribute), false)[0]
                                                   : null;
            if (implementedBy != null)
            {
                Attributes.CheckForMisplacedScopeAnnotations(rawType, source, errors);
                return CreateImplementedByBinding(key, scoping, implementedBy, errors);
            }

            // Handle @ProvidedBy.
            ProvidedByAttribute providedBy = rawType.GetCustomAttributes(typeof(ProvidedByAttribute), false).Length != 0
                                             ? (ProvidedByAttribute)rawType.GetCustomAttributes(typeof(ProvidedByAttribute), false)[0]
                                             : null;
            if (providedBy != null)
            {
                Attributes.CheckForMisplacedScopeAnnotations(rawType, source, errors);
                return CreateProvidedByBinding(key, scoping, providedBy, errors);
            }
            return ConstructorBindingImpl<T>.Create(this, key, null, source, scoping, errors, jitBinding && options.jitDisabled);
        }

        private class ProvidedByBindingInternalFactory<T> : InternalFactory<T>
        {
            private Type rawType;

            private Key providerKey;//泛型参数为IProvider<T>类型

            private Type providerType;

            private IBindingImpl providerBinding;//泛型参数为IProvider<T>类型

            /// <summary>
            /// </summary>
            /// <param name="rawType"></param>
            /// <param name="providerType"></param>
            /// <param name="providerKey">泛型参数为IProvider<T>类型</param>
            /// <param name="providerBinding">//泛型参数为IProvider<T>类型</param>
            public ProvidedByBindingInternalFactory(Type rawType, Type providerType, Key providerKey, IBindingImpl providerBinding)
            {
                Preconditions.CheckSubGenericParameter<IProvider<T>>(providerKey);
                Preconditions.CheckSubGenericParameter<IProvider<T>>(providerBinding);
                this.rawType = rawType;
                this.providerType = providerType;
                this.providerKey = providerKey;
                this.providerBinding = providerBinding;
            }

            public T Get(Errors errors, InternalContext context, Dependency dependency, bool linked)
            {
                errors = errors.WithSource(providerKey);
                IProvider provider = (IProvider)providerBinding.GetInternalFactory().Get(errors, context, dependency, true);
                try
                {
                    object o = provider.Get();
                    if (o != null && !rawType.IsInstanceOfType(o))
                    {
                        throw errors.SubtypeNotProvided(providerType, rawType).ToException();
                    }
                    // protected by isInstance() check above
                    T t = (T)o;
                    return t;
                }
                catch (Exception e)
                {
                    throw errors.ErrorInProvider(e).ToException();
                }
            }

            object InternalFactory.Get(Errors errors, InternalContext context, Dependency dependency, bool linked)
            {
                return Get(errors, context, dependency, linked);
            }
        }

        /// <summary>
        ///  为一个具有[ProvidedBy]元特性的类型创建一个绑定
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="scoping"></param>
        /// <param name="providedBy"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        BindingImpl<T> CreateProvidedByBinding<T>(Key<T> key, Scoping scoping, ProvidedByAttribute providedBy, Errors errors)
        {
            //final Class<?> rawType = key.getTypeLiteral().getRawType();
            //final Class<? extends Provider<?>> providerType = providedBy.value();
            Type rawType = key.TypeLiteral;
            Type providerType = providedBy.Value;

            // 确保不是同一个类型. TODO: Can we check for deeper loops?
            if (providerType == rawType)
            {
                throw errors.RecursiveProviderType().ToException();
            }

            // 假定提供者提供一个合适的类型，我们将在运行时两次检查  (providerType类型的父类必须是IProvider<T>类型）
            Key providerKey = Key<object>.GetForType(providerType);
            //泛型参数必须为Provider<?>泛型类型
            IBindingImpl providerBinding = GetBindingOrThrowForNoGeneric(providerKey, errors, JitLimitation.NEW_OR_EXISTING_JIT);

            InternalFactory<T> internalFactory = new ProvidedByBindingInternalFactory<T>(rawType, providerType, providerKey, providerBinding);

            object source = rawType;
            return new LinkedProviderBindingImpl<T>(
                this,
                key,
                source,
                Scoping.Scope<T>(key, this, internalFactory, source, scoping),
                scoping,
                providerKey);
        }

        private class ImplementedByBindingInternalFactory<T> : InternalFactory<T>
        {
            private IBindingImpl targetBinding;

            private Key targetKey;

            /// <summary>
            /// </summary>
            /// <param name="targetKey">泛型参数必须为T的子类</param>
            /// <param name="targetBinding"></param>
            public ImplementedByBindingInternalFactory(Key targetKey, IBindingImpl targetBinding)
            {
                Preconditions.CheckSubGenericParameter<T>(targetKey);
                Preconditions.CheckSubGenericParameter<T>(targetBinding);
                this.targetKey = targetKey;
                this.targetBinding = targetBinding;
            }

            public T Get(Errors errors, InternalContext context, Dependency dependency, bool linked)
            {
                return (T)targetBinding.GetInternalFactory().Get(
                       errors.WithSource(targetKey), context, dependency, true);
            }

            object InternalFactory.Get(Errors errors, InternalContext context, Dependency dependency, bool linked)
            {
                return Get(errors, context, dependency, linked);
            }
        }

        /// <summary>
        /// 为一个具有[ImplementedBy]元特性的类型创建一个绑定
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="scoping"></param>
        /// <param name="implementedBy"></param>
        /// <param name="errors"></param>
        /// <returns></returns>   
        private BindingImpl<T> CreateImplementedByBinding<T>(Key<T> key, Scoping scoping, ImplementedByAttribute implementedBy, Errors errors)
        {
            Type rawType = key.TypeLiteral;
            Type implementationType = implementedBy.Value;

            // 确保不是相同类型. TODO: Can we check for deeper cycles?
            if (implementationType == rawType)
            {
                throw errors.RecursiveImplementationType().ToException();
            }

            // Make sure implementationType extends type.
            if (!rawType.IsAssignableFrom(implementationType))
            {
                throw errors.NotASubtype(implementationType, rawType).ToException();
            }

            // 在上面检查之后, 转换是安全的.
            //Class<? extends T> subclass = (Class<? extends T>) implementationType;

            // 查找目标binding
            Key targetKey = Key<T>.GetForType(implementationType);
            IBindingImpl targetBinding = GetBindingOrThrowForNoGeneric(targetKey, errors, JitLimitation.NEW_OR_EXISTING_JIT);

            InternalFactory<T> internalFactory = new ImplementedByBindingInternalFactory<T>(targetKey, targetBinding);

            object source = rawType;
            return new LinkedBindingImpl<T>(
                this,
                key,
                source,
                Scoping.Scope<T>(key, this, internalFactory, source, scoping),
                scoping,
                targetKey);
        }

        /// <summary>
        /// 试图在根注入器中为指定的key创建一个即时的binding，直到此注入器被tried时将回落到其他祖先注入器
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        private BindingImpl<T> CreateJustInTimeBindingRecursive<T>(Key<T> key, Errors errors)
        {
            // ask the parent to create the JIT binding
            if (parent != null && !parent.options.jitDisabled)
            {
                try
                {
                    return parent.CreateJustInTimeBindingRecursive(key, new Errors());
                }
                catch (ErrorsException ignored)
                {
                }
            }

            if (state.IsBlacklisted(key))
            {
                throw errors.ChildBindingAlreadySet(key).ToException();
            }

            BindingImpl<T> binding = CreateJustInTimeBinding(key, errors);
            state.Parent.Blacklist(key);
            if (jitBindings.ContainsKey(key))
            {
                jitBindings[key] = binding;
            }
            else
            {
                jitBindings.Add(key, binding);
            }
            return binding;
        }

        /// <summary>
        /// 返回一个通过解析key创建的即时的binding。用于创建即时binding的策略为：
        /// <list type="li">
        ///   1.内部化Providers。如果请求的binding是用于IProvider，我们讲代理绑定到T泛型类型
        ///   2.转换常数
        ///   3.ImplementedBy and ProvidedBy元特性，仅仅用于未注释的keys
        ///   4.原始类型的构造器。仅仅用于未注释的keys
        /// </list>
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="key"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        /// <exception cref="ErrorsException">绑定创建失败</exception>
        private BindingImpl<T> CreateJustInTimeBinding<T>(Key<T> key, Errors errors)
        {
            int numErrorsBefore = errors.Size;

            if (state.IsBlacklisted(key))
            {
                throw errors.ChildBindingAlreadySet(key).ToException();
            }

            // Handle cases where T is a Provider<?>.
            if (IsProvider(key))
            {
                // These casts are safe. We know T extends Provider<X> and that given Key<Provider<X>>,
                // createProviderBinding() will return BindingImpl<Provider<X>>.
                BindingImpl<T> binding = (BindingImpl<T>)CreateProviderBinding((Key)key, errors);
                return binding;
            }

            // Handle cases where T is a MembersInjector<?>
            if (IsMembersInjector(key))
            {
                // These casts are safe. T extends MembersInjector<X> and that given Key<MembersInjector<X>>,
                // createMembersInjectorBinding() will return BindingImpl<MembersInjector<X>>.
                BindingImpl<T> binding = (BindingImpl<T>)CreateMembersInjectorBinding((Key)key, errors);
                return binding;
            }

            //视图转换一个常数字符绑定到请求的类型中
            BindingImpl<T> convertedBinding = ConvertConstantStringBinding(key, errors);
            if (convertedBinding != null)
            {
                return convertedBinding;
            }

            // 如果key具有一个元特性...
            if (key.HasAttributeType)
            {
                // 查找一个不具有元特性的绑定或者返回null.
                if (key.HasAttributes)
                {
                    try
                    {
                        Errors ignored = new Errors();
                        return GetBindingOrThrow(key.WithoutAttributes, ignored, JitLimitation.NO_JIT);
                    }
                    catch (ErrorsException ignored)
                    {
                        // throw with a more appropriate message below
                    }
                }
                throw errors.MissingImplementation(key).ToException();
            }

            object source = key.TypeLiteral;
            BindingImpl<T> unbinding = CreateUninitializedBinding(key, Scoping.UNSCOPED, source, errors, true);
            errors.ThrowIfNewErrors(numErrorsBefore);
            InitializeJitBinding(unbinding, errors);
            return unbinding;
        }

        public InternalFactory<T> GetInternalFactory<T>(Key<T> key, Errors errors, JitLimitation jitType)
        {
            return GetBindingOrThrow(key, errors, jitType).InternalFactory;
        }

        /// <summary>
        /// 非泛型的方法
        /// </summary>
        /// <param name="key"></param>
        /// <param name="errors"></param>
        /// <param name="jitType"></param>
        /// <returns></returns>
        public InternalFactory GetInternalFactory(Key key, Errors errors, JitLimitation jitType)
        {
            //只能通过反射调用泛型方法
            if (!key.GetType().IsGenericType)
                throw new ArgumentException("the key must generic type");
            foreach (MethodInfo method in GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                if (method.Name == "GetInternalFactory")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (InternalFactory)method.MakeGenericMethod(key.GetType().GetGenericArguments()[0])
                                     .Invoke(this, new object[] { key, errors, jitType })
                                     .GetType().GetProperty("InternalFactory");
                    }
                    else if (method.IsGenericMethod)
                    {
                        //不是泛型定义方法，可以直接调用
                        return (InternalFactory)method.Invoke(this, new object[] { key, errors, jitType })
                                     .GetType().GetProperty("InternalFactory");
                    }
                }
            }
            throw new IllegalStateException("GetInternalFactory generic method is not defined!");
        }

        public IDictionary<Key<K>, IBinding<I>> GetBindings<K, I>()
        {
            IDictionary<Key<K>, IBinding<I>> bindings = new Dictionary<Key<K>, IBinding<I>>();
            foreach (Key k in Bindings.Keys)
            {
                if (k is Key<K> && Bindings[k] is IBinding<I>)
                {
                    bindings.Add((Key<K>)k, (IBinding<I>)Bindings[k]);
                }
            }
            return bindings;
        }

        public IDictionary<Key, IBinding> Bindings
        {
            get
            {
                return state.GetExplicitBindingsThisLevel();
            }
        }

        IDictionary<Key, IBinding> Injector.Bindings
        {
            get { return Bindings; }
        }

        public IDictionary<Key<K>, IBinding<I>> GetAllBindings<K, I>()
        {
            IDictionary<Key<K>, IBinding<I>> bindings = new Dictionary<Key<K>, IBinding<I>>();
            foreach (Key k in AllBindings.Keys)
            {
                if (k is Key<K> && AllBindings[k] is IBinding<I>)
                {
                    bindings.Add((Key<K>)k, (IBinding<I>)AllBindings[k]);
                }
            }
            return bindings;
        }

        public IDictionary<Key, IBinding> AllBindings
        {
            get
            {
                Dictionary<Key, IBinding> jit = new Dictionary<Key, IBinding>();
                foreach (Key k in jitBindings.Keys)
                {
                    jit.Add(k, jitBindings[k]);
                }
                lock (state.Lock())
                {
                    return new ImmutableDictionaryBuilder<Key, IBinding>()
                                   .PutAll(state.GetExplicitBindingsThisLevel())
                                   .PutAll(jit)
                                   .Build();
                }
            }
        }

        IDictionary<Key, IBinding> Injector.AllBindings
        {
            get { return AllBindings; }
        }

        public IDictionary<Type, IScope> ScopeBindings
        {
            get
            {
                return ImmutableDictionary<Type, IScope>.CopyOf(state.Scopes);
            }
        }

        public ISet<Spi.TypeConverterBinding> TypeConverterBindings
        {
            get
            {
                return ImmutableSet<Spi.TypeConverterBinding>.CopyOf<Spi.TypeConverterBinding, Spi.TypeConverterBinding>(state.GetConvertersThisLevel());
            }
        }

        internal class BindingsMultimap
        {
            readonly IDictionary<Type, List<IBinding>> multimap = new Dictionary<Type, List<IBinding>>();//value为Binding<?>

            internal void Put<T>(IBinding<T> binding)
            {
                List<IBinding> bindingsForType = null;
                if (!multimap.ContainsKey(typeof(T)))
                {
                    bindingsForType = Lists.NewArrayList<IBinding>();
                    multimap.Add(typeof(T), bindingsForType);
                }
                else if (bindingsForType == null)
                {
                    bindingsForType = Lists.NewArrayList<IBinding>();
                    multimap[typeof(T)] = bindingsForType;
                }
                else
                {
                    multimap[typeof(T)].Add(binding);
                }
            }

            internal void Put(Type type, IBinding binding)
            {
                List<IBinding> bindingsForType = null;
                if (!multimap.ContainsKey(type))
                {
                    bindingsForType = Lists.NewArrayList<IBinding>();
                    multimap.Add(type, bindingsForType);
                }
                else if (bindingsForType == null)
                {
                    bindingsForType = Lists.NewArrayList<IBinding>();
                    multimap[type] = bindingsForType;
                }
                else
                {
                    multimap[type].Add(binding);
                }
            }

            internal List<IBinding<T>> GetAll<T>()
            {
                List<IBinding> bindings = multimap[typeof(T)];
                List<IBinding<T>> result = new List<IBinding<T>>(bindings.Count);
                foreach (IBinding b in bindings)
                {
                    result.Add((IBinding<T>)b);
                }
                return result;
            }
        }

        /// <summary>
        /// 返回参数注入器，如果没有参数则返回null
        /// </summary>
        /// <param name="parameters"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        internal SingleParameterInjector[] GetParametersInjectors(IList<Dependency> parameters, Errors errors)
        {
            if (parameters.Count == 0)
            {
                return null;
            }

            int numErrorsBefore = errors.Size;
            SingleParameterInjector[] result = new SingleParameterInjector[parameters.Count];
            int i = 0;
            foreach (Dependency parameter in parameters)
            {
                try
                {
                    result[i++] = CreateParameterInjector(parameter, errors.WithSource(parameter));
                }
                catch (ErrorsException rethrownBelow)
                {
                    // rethrown below
                }
            }

            errors.ThrowIfNewErrors(numErrorsBefore);
            return result;
        }

        internal SingleParameterInjector<T> CreateParameterInjector<T>(Dependency<T> dependency, Errors errors)
        {
            InternalFactory<T> factory = GetInternalFactory(dependency.Key, errors, JitLimitation.NO_JIT);
            return new SingleParameterInjector<T>(dependency, factory);
        }

        /// <summary>
        /// 非泛型方法！
        /// </summary>
        /// <param name="dependency"></param>
        /// <param name="errors"></param>
        /// <returns></returns>
        internal SingleParameterInjector CreateParameterInjector(Dependency dependency, Errors errors)
        {
            foreach (MethodInfo method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
            {
                if (method.Name == "CreateParameterInjector")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (SingleParameterInjector)method.MakeGenericMethod(dependency.GetType().GetGenericArguments()[0]).Invoke(this, new object[] { dependency, errors });
                    }
                    else if (method.IsGenericMethod)
                    {
                        return (SingleParameterInjector)method.Invoke(this, new object[] { dependency, errors });
                    }
                }
            }
            throw new NotImplementedException("the generic CreateParameterInjector do not implements");
        }

        /// <summary>
        /// 方法调用对象
        /// </summary>
        internal interface MethodInvoker
        {
            /// <summary>
            /// 调用方法
            /// </summary>
            /// <param name="target"></param>
            /// <param name="parameters"></param>
            /// <returns></returns>
            /// <exception cref="MethodAccessException"></exception>
            /// <exception ref="TargetInvocationException"></exception>
            object Invoke(object target, params object[] parameters);
        }

        /** Cached constructor injectors for each type */
        internal readonly ConstructorInjectorStore constructors;

        //为每一个类型缓存域、属性和方法
        internal MembersInjectorStore membersInjectorStore;

        public void InjectMembers(object instance)
        {
            IMembersInjector membersInjector = GetMembersInjector(instance.GetType());
            membersInjector.InjectMembers(instance);
        }

        public IMembersInjector<T> GetMembersInjector<T>()
        {
            Errors errors = new Errors(typeof(T));
            try
            {
                return membersInjectorStore.Get<T>(typeof(T), errors);
            }
            catch (ErrorsException e)
            {
                throw new ConfigurationException(errors.Merge(e.Errors).Messages);
            }
        }

        public IMembersInjector GetMembersInjector(Type genericType)
        {
            foreach (MethodInfo method in GetType().GetMethods(BindingFlags.NonPublic | BindingFlags.Instance))
            {
                if (method.Name == "GetMembersInjector")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (IMembersInjector)method.MakeGenericMethod(genericType).Invoke(this, null);
                    }
                    else if (method.IsGenericMethod)
                    {
                        //不是泛型类型定义，可以直接调用
                        return (IMembersInjector)method.Invoke(this, null);
                    }
                }
            }
            throw new NotImplementedException("the generic GetMembersInjector do not implements");
        }

        public IProvider GetProvider(Type providerGenericType)
        {
            return GetProvider(Key<object>.GetForType(providerGenericType));
        }

        public IProvider<T> GetProvider<T>(Key<T> key)
        {
            Errors errors = new Errors(key);
            try
            {
                //key.DebugHashCode();
                IProvider<T> result = GetProviderOrThrow(key, errors);
                errors.ThrowIfNewErrors(0);
                return result;
            }
            catch (ErrorsException e)
            {
                throw new ConfigurationException(errors.Merge(e.Errors).Messages);
            }
        }

        /// <summary>
        /// 非泛型方法！
        /// </summary>
        /// <param name="key"></param>
        /// <returns></returns>
        private IProvider GetProvider(Key key)
        {
            foreach (MethodInfo method in GetType().GetMethods(BindingFlags.Public | BindingFlags.Instance))
            {
                if (method.Name == "GetProvider")
                {
                    if (method.IsGenericMethodDefinition)
                    {
                        return (IProvider)method.MakeGenericMethod(key.GetType().GetGenericArguments()[0]).Invoke(this, new object[] { key });
                    }
                    else if (method.IsGenericMethod)
                    {
                        //不是泛型定义方法，可以直接调用
                        return (IProvider)method.Invoke(this, new object[] { key });
                    }
                }
            }
            throw new NotImplementedException("the generic GetProvider do not implements");
        }

        internal class ThrowErrorProvider<T> : IProvider<T>
        {
            private Dependency<T> dependency;

            private InternalFactory<T> factory;

            private Errors errors;

            private InjectorImpl injector;

            public ThrowErrorProvider(InjectorImpl injector, InternalFactory<T> factory, Dependency<T> dependency, Errors errors)
            {
                this.injector = injector;
                this.factory = factory;
                this.dependency = dependency;
                this.errors = errors;
            }

            private class ProviderContextualCallable : ContextualCallable<T>
            {
                private ThrowErrorProvider<T> outer;

                public ProviderContextualCallable(ThrowErrorProvider<T> outer)
                {
                    this.outer = outer;
                }

                public T Call(InternalContext context)
                {
                    Dependency previous = context.SetDependency(outer.dependency);
                    try
                    {
                        return outer.factory.Get(outer.errors, context, outer.dependency, false);
                    }
                    finally
                    {
                        context.SetDependency(previous);
                    }
                }
            }

            public T Get()
            {
                Errors errors = new Errors(dependency);
                try
                {
                    T t = injector.CallInContext(new ProviderContextualCallable(this));
                    errors.ThrowIfNewErrors(0);
                    return t;
                }
                catch (ErrorsException e)
                {
                    throw new ProvisionException(errors.Merge(e.Errors).Messages);
                }
            }

            object IProvider.Get()
            {
                return Get();
            }

            public override string ToString()
            {
                return factory.ToString();
            }
        }

        internal IProvider<T> GetProviderOrThrow<T>(Key<T> key, Errors errors)
        {
            InternalFactory<T> factory = GetInternalFactory(key, errors, JitLimitation.NO_JIT);
            Dependency<T> dependency = Dependency<T>.Get(key);
            return new ThrowErrorProvider<T>(this, factory, dependency, errors);
        }

        public T GetInstance<T>(Key<T> key)
        {
            return GetProvider(key).Get();
        }

        public object GetInstance(Type clazz)
        {
            return GetProvider(clazz).Get();
        }

        readonly ThreadLocal<object[]> localContext;

        /// <summary>
        /// 查找线程本地上下文。如果必要，则创建（或删除）一个新的上下文
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="callable"></param>
        /// <returns></returns>
        internal T CallInContext<T>(ContextualCallable<T> callable)
        {
            object[] reference = localContext.Value;
            if (reference[0] == null)
            {
                reference[0] = new InternalContext();
                try
                {
                    return callable.Call((InternalContext)reference[0]);
                }
                finally
                {
                    // Only clear the context if this call created it.
                    reference[0] = null;
                }
            }
            else
            {
                // Someone else will clean up this context.
                return callable.Call((InternalContext)reference[0]);
            }
        }

        public override string ToString()
        {
            return new ToStringBuilder(typeof(Injector))
                .Add("bindings", state.GetExplicitBindingsThisLevel().Values)
                .ToString();
        }
    }

}
